package com.ssm.jvm;


import java.io.FileInputStream;
import java.lang.reflect.Method;

/**
 * 加载多个相同的类
 *
 */
public class WebAppClassLoaderTest extends ClassLoader {

    private String classPath;

    public WebAppClassLoaderTest(String classPath) {
        this.classPath = classPath;
    }

    private byte[] loadByte(String name) throws Exception {
        name = name.replaceAll("\\.", "/");
        FileInputStream fis = new FileInputStream(classPath + "/" + name
                + ".class");
        int len = fis.available();
        byte[] data = new byte[len];
        fis.read(data);
        fis.close();
        return data;
    }


    protected Class<?> loadClass(String name, boolean resolve)
            throws ClassNotFoundException {
        synchronized (getClassLoadingLock(name)) {
            // First, check if the class has already been loaded
            Class<?> c = findLoadedClass(name);
            if (c == null) {
                if (name.startsWith("com.ssm")) {
                    c = findClass(name);
                } else {
                    // 交由父加载器去加载
                    c = this.getParent().loadClass(name);
                }
            }
            if (resolve) {
                resolveClass(c);
            }
            return c;
        }
    }

    @Override
    protected Class<?> findClass(String name) throws ClassNotFoundException {
        try {
            byte[] data = loadByte(name);
            //defineClass将一个字节数组转为Class对象，这个字节数组是class文件读取后最终的字节数组。
            return defineClass(name, data, 0, data.length);
        } catch (Exception e) {
            e.printStackTrace();
            throw new ClassNotFoundException();
        }
    }

    public static void main(String args[]) throws Exception {
        //初始化自定义类加载器，会先初始化父类ClassLoader，其中会把自定义类加载器的父加载器设置为应用程序类加载器AppClassLoader
        WebAppClassLoaderTest classLoader = new WebAppClassLoaderTest("/Users/zhengshaohong/Desktop/webapp/test1");
        //盘创建~/Desktop/webapp/test1 目录，将Test类的复制类Test.class丢入该目录
        Class clazz = classLoader.loadClass("com.ssm.jvm.Test");
        Object obj = clazz.newInstance();
        Method method = clazz.getDeclaredMethod("outHello", null);
        method.invoke(obj, null);
        System.out.println(clazz.getClassLoader());

        System.out.println();

        WebAppClassLoaderTest classLoader1 = new WebAppClassLoaderTest("/Users/zhengshaohong/Desktop/webapp/test2");
        //创建 ~/Desktop/webapp/test1 目录，将Test类的复制类Test.class丢入该目录
        Class clazz1 = classLoader1.loadClass("com.ssm.jvm.Test");
        Object obj1 = clazz1.newInstance();
        Method method1 = clazz1.getDeclaredMethod("outHello", null);
        method1.invoke(obj1, null);
        System.out.println(clazz1.getClassLoader());

    }
}

